package com.itheima.stock.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.stock.entity.*;
import com.itheima.stock.mapper.*;
import com.itheima.stock.properties.MarketIndexProperties;
import com.itheima.stock.response.ResponsePage;
import com.itheima.stock.response.ResponseResult;
import com.itheima.stock.service.StockService;
import com.itheima.stock.util.DateTimeUtil;
import com.itheima.stock.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.swing.text.html.Option;
import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author zby
 * @created 2024-06-23 16:34
 * @description 股票业务实现类
 */
@Service
public class StockServiceImpl implements StockService {


    private final StockBusinessMapper stockBusinessMapper;

    private final MarketIndexProperties marketIndexProperties;

    private final StockMarketIndexInfoMapper marketIndexInfoMapper;

    private final StockMarketLogPriceMapper marketLogPriceMapper;
    private final StockBlockRtInfoMapper blockRtInfoMapper;

    private final StockRtInfoMapper stockRtInfoMapper;

    public StockServiceImpl(StockBusinessMapper stockBusinessMapper, MarketIndexProperties marketIndexProperties, StockMarketIndexInfoMapper marketIndexInfoMapper, StockMarketLogPriceMapper marketLogPriceMapper, StockBlockRtInfoMapper blockRtInfoMapper, StockRtInfoMapper stockRtInfoMapper) {
        this.stockBusinessMapper = stockBusinessMapper;
        this.marketIndexProperties = marketIndexProperties;
        this.marketIndexInfoMapper = marketIndexInfoMapper;
        this.marketLogPriceMapper = marketLogPriceMapper;
        this.blockRtInfoMapper = blockRtInfoMapper;
        this.stockRtInfoMapper = stockRtInfoMapper;
    }


    @Override
    public ResponsePage<MoreAllVO> page(Integer page, Integer pageSize) {
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //TODO 模拟数据
        last = LocalDateTime.parse("2021-12-30 09:32:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //TODO 模拟数据
        PageHelper.startPage(page, pageSize);
        List<MoreAllVO> stockRtInfos = stockRtInfoMapper.selectMore(last);
        Page<MoreAllVO> p = (Page<MoreAllVO>) stockRtInfos;
        return ResponsePage.<MoreAllVO>builder()
                .totalRows(p.getTotal())
                .size(p.size())
                .totalPages(p.getTotal())
                .pageNum(p.getPageNum())
                .pageSize(p.getPageSize())
                .rows(p.getResult())
                .build();
    }

    @Override
    public List<StockUpdownVO> stockIncrease() {
        //拿到最近的一次交易股票的时间
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //TODO 模拟数据
        last = LocalDateTime.parse("2021-12-30 09:32:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //TODO 模拟数据
        //拿到当前时间的所有数据
        List<StockRtInfo> stockRtInfos = stockRtInfoMapper.selectByCurTime(last);

        List<StockUpdownVO> voList = new ArrayList<>();
        stockRtInfos.stream().forEach(stock -> {
            StockUpdownVO vo = new StockUpdownVO();
            vo.setCode(stock.getStockCode());//代码
            vo.setName(stock.getStockName());//名称
            vo.setTradePrice(stock.getCurPrice());//当前价格
            vo.setTradeAmt(stock.getTradeAmount());//总手
            vo.setPreClosePrice(stock.getPreClosePrice());//前收盘价
            vo.setTradeVol(stock.getTradeVolume());//成交额
            vo.setCurDate(stock.getCurTime().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            //涨跌
            BigDecimal upDown = stock.getCurPrice().subtract(stock.getPreClosePrice());
            //涨幅
            BigDecimal increase = (stock.getCurPrice().subtract(stock.getPreClosePrice())).divide(stock.getPreClosePrice(), new MathContext(6)).multiply(BigDecimal.valueOf(1.0));
            //振幅
            BigDecimal amplitude = (stock.getMaxPrice().subtract(stock.getMinPrice())).divide(stock.getPreClosePrice(), new MathContext(6)).multiply(BigDecimal.valueOf(1.0));
            vo.setUpDown(upDown);
            vo.setIncrease(increase);
            vo.setAmplitude(amplitude);
            voList.add(vo);
        });
        List<StockUpdownVO> list = voList.stream().sorted((o1, o2) -> {
            return o2.getIncrease().subtract(o1.getIncrease()).intValue();
        }).limit(10).toList();

        return list;
    }

    @Override
    public List<SectorAllVO> sectorAll() {
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //TODO 模拟数据
        String mockDate = "2021-12-21 00:00:00";
        last = LocalDateTime.parse(mockDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime begin = DateTimeUtil.getOpenDate(last);
        LocalDateTime end = DateTimeUtil.getCloseDate(last);
        //1查询数据库
        List<StockBlockRtInfo> blockRtInfos = blockRtInfoMapper.selectAllByDate(begin, end);
        //2封装数据返回
        return blockRtInfos.stream().map(info -> {
            SectorAllVO vo = new SectorAllVO();
            vo.setAvgPrice(info.getAvgPrice());
            vo.setName(info.getBlockName());
            vo.setCompanyNum(info.getCompanyNum());
            vo.setTradeAmt(info.getTradeAmount());
            vo.setUpdownRate(info.getUpdownRate());
            vo.setTradeVol(info.getTradeVolume());
            vo.setCode(info.getLabel());
            vo.setCurDate(info.getCurTime().toLocalDate().toString());
            return vo;
        }).toList();
    }

    @Override
    public List<MarketIndexVO> innerIndexAll() {
        //1.获取大盘指数编码（考虑到后期还有国外的大盘指数编码，采用配置属性类的形式来注入）
        List<String> ids = marketIndexProperties.getInner();
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //TODO 模拟数据
        String mockDate = "20211226105600";
        last = LocalDateTime.parse(mockDate, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        //2.查询数据库
        List<StockMarketIndexInfo> infoList = marketIndexInfoMapper.selectByIdsAndTime(ids, last);

        List<StockMarketLogPrice> logList = marketLogPriceMapper.selectByIdsAndTime(ids, last.toLocalDate());
        //3.封装数据返回
        return infoList.stream().map((info -> {
            MarketIndexVO vo = new MarketIndexVO();
            vo.setCode(info.getMarkId());
            vo.setName(info.getMarkName());
            vo.setCurDate(info.getCurTime().toLocalDate().toString());
            vo.setTradeAmt(info.getTradeAccount());
            vo.setTradePrice(info.getCurrentPrice());
            vo.setUpDown(info.getUpdownRate());
            vo.setTradeVol(info.getTradeVolume());
            //对每一个vo都需要去匹配log里的开盘价和前收盘价
            logList.forEach(log -> {
                if (info.getMarkId().equals(log.getMarketCode())) {
                    vo.setOpenPrice(log.getOpenPrice());
                    vo.setPreClosePrice(log.getPreClosePrice());
                }
            });
            return vo;
        })).toList();
    }

    @Override
    public List<StockBusiness> getStockBusiness() {

        return stockBusinessMapper.selectAll();
    }

    @Override
    public StockCountVO<OptionVO> count() {

        //TODO 模拟数据
        LocalDateTime begin = LocalDateTime.parse("2022-01-06 09:25:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse("2022-01-06 14:25:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //TODO 模拟数据
        //涨停
        List<OptionVO> up = stockRtInfoMapper.upDown(begin, end,true);
        //跌停
        List<OptionVO> down = stockRtInfoMapper.upDown(begin, end,false);

        return StockCountVO.<OptionVO>builder()
                .upList(up)
                .downList(down)
                .build();
    }

    @Override
    public StockTradeAmtVO tradeAmt() {

        //拿到T日的开始时间和结束时间
        LocalDateTime t = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        LocalDateTime t_openDate = DateTimeUtil.getOpenDate(t);
        LocalDateTime t_closeDate = DateTimeUtil.getCloseDate(t);
        //拿到T-1日的开始时间和结束时间
        LocalDateTime t_1 = DateTimeUtil.getPreviousTradingDay(LocalDateTime.now());
        LocalDateTime t_1_openDate = DateTimeUtil.getOpenDate(t_1);
        LocalDateTime t_1_closeDate = DateTimeUtil.getCloseDate(t_1);
        //TODO 模拟数据
        //拿到T日的开始时间和结束时间2021-12-31 09:30:00' AND '2021-12-31 14:30:00'
        t_openDate = LocalDateTime.parse("2021-12-28 09:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        t_closeDate = LocalDateTime.parse("2021-12-28 14:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //拿到T-1日的开始时间和结束时间2021-12-30 09:30:00' AND '2021-12-30 14:30:00'
        t_1_openDate = LocalDateTime.parse("2021-12-27 09:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        t_1_closeDate = LocalDateTime.parse("2021-12-27 14:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //TODO 模拟数据
        //操作数据库拿数据
        List<String> ids = marketIndexProperties.getInner();
        List<OptionVO> list = marketIndexInfoMapper.selectAmt(t_1_openDate,t_closeDate,ids);
        LocalDate tDate = t_closeDate.toLocalDate();
        LocalDate t_1Date = t_1_openDate.toLocalDate();
        List<OptionVO> tList = list.stream().filter(e -> {
            LocalDateTime parse = LocalDateTime.parse(e.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            LocalDate eDate = parse.toLocalDate();
            return eDate.isEqual(tDate);
        }).toList();
        List<OptionVO> t_1List = list.stream().filter(e -> {
            LocalDateTime parse = LocalDateTime.parse(e.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            LocalDate eDate = parse.toLocalDate();
            return eDate.isEqual(t_1Date);
        }).toList();
        return StockTradeAmtVO.builder()
                .volList(tList)
                .yesVolList(t_1List)
                .build();
    }

    @Override
    public StockStockUpDownVO stockUpDown() {

        LocalDateTime tDate = LocalDateTime.parse("2022-01-06 09:55:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        List<UpDownVO> list = stockRtInfoMapper.select(tDate);
        //TODO 优化前端的排序问题

        return StockStockUpDownVO.builder()
                .time(tDate)
                .infos(list)
                .build();
    }

    @Override
    public List<StockTimeSharingVO> timeSharing(String code) {

        //2021-12-30 09:30:00  2021-12-30 14:30:00
        //TODO 模拟数据
        LocalDateTime begin = LocalDateTime.parse("2021-12-30 09:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse("2021-12-30 14:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //TODO 模拟数据
        List<StockRtInfo> list = stockRtInfoMapper.selectByBeginEndTime(begin, end,code);
        return list.stream().map(e->{
            return StockTimeSharingVO.builder()
                    .date(e.getCurTime())
                    .tradeAmt(e.getTradeAmount())
                    .code(e.getStockCode())
                    .lowPrice(e.getMinPrice())
                    .preClosePrice(e.getPreClosePrice())
                    .name(e.getStockName())
                    .highPrice(e.getMaxPrice())
                    .openPrice(e.getOpenPrice())
                    .tradeVol(e.getTradeVolume())
                    .tradePrice(e.getCurPrice())
                    .build();
        }).toList();

    }

    @Override
    public List<StockDklineVO> dkline(String code) {


        //TODO 模拟数据
        LocalDateTime begin = LocalDateTime.parse("2021-12-30 09:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse("2021-12-30 14:30:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        //TODO 模拟数据
        List<StockRtInfo> list = stockRtInfoMapper.selectByBeginEndTime(begin, end,code);

        return list.stream().map(e -> {
            return StockDklineVO.builder()
                    .date(e.getCurTime())
                    .tradeAmt(e.getTradeAmount())
                    .code(e.getStockCode())
                    .lowPrice(e.getMinPrice())
                    .preClosePrice(e.getPreClosePrice())
                    .name(e.getStockName())
                    .highPrice(e.getMaxPrice())
                    .openPrice(e.getOpenPrice())
                    .tradeVol(e.getTradeVolume())
                    .closePrice(e.getPreClosePrice())
                    .build();
        }).toList();
    }
}